<template>
  <div class="media-wall" :style="{ minHeight }" ref="root">
    <MediaTabs class="tabs pt-2" v-model="currTab" :tabs="tabs"></MediaTabs>
    <MediaRow
      v-if="isVideoPhoto"
      v-show="atVideo"
      class="px-4"
      :items="videoData"
      :loading="videoLoading"
      :no-more="videoNoMore"
      :preview-mode="previewMode"
      :preview-visitor="previewVisitor"
      @intersect="onIntersect"
      @click:item="onItemClick"
      @bounding="onBounding"
      @selected="onSelected"
    ></MediaRow>
    <MediaRow
      v-if="isVideoPhoto"
      v-show="atPhoto"
      class="px-4"
      :items="photoData"
      :loading="photoLoading"
      :no-more="photoNoMore"
      :preview-mode="previewMode"
      :preview-visitor="previewVisitor"
      @intersect="onIntersect"
      @click:item="onItemClick"
      @bounding="onBounding"
      @selected="onSelected"
    ></MediaRow>
    <MediaRow
      v-if="isSubsShopFree || isOnlySubs"
      v-show="atSubs"
      class="px-4"
      :items="subsData"
      :loading="subsLoading"
      :no-more="subsNoMore"
      :preview-mode="previewMode"
      :preview-visitor="previewVisitor"
      @intersect="onIntersect"
      @click:item="onItemClick"
      @bounding="onBounding"
      @selected="onSelected"
    ></MediaRow>
    <MediaRow
      v-if="isSubsShopFree"
      v-show="atShop"
      class="px-4"
      :items="shopData"
      :loading="shopLoading"
      :no-more="shopNoMore"
      :preview-mode="previewMode"
      :preview-visitor="previewVisitor"
      @intersect="onIntersect"
      @click:item="onItemClick"
      @bounding="onBounding"
      @selected="onSelected"
    ></MediaRow>
    <MediaRow
      v-if="isSubsShopFree"
      v-show="atFree"
      class="px-4"
      :items="freeData"
      :loading="freeLoading"
      :no-more="freeNoMore"
      :preview-mode="previewMode"
      :preview-visitor="previewVisitor"
      @intersect="onIntersect"
      @click:item="onItemClick"
      @bounding="onBounding"
      @selected="onSelected"
    ></MediaRow>
  </div>
</template>
<script setup>
import { computed, onMounted, provide, ref, watch } from 'vue'
import { useElementBounding, useWindowSize } from '@vueuse/core'
import { storeToRefs } from 'pinia'
import { useAppStore } from '@/store/app'
import { usePopupMessageStore } from '@/store/popup-message'
import { $t } from '@/i18n'
import { findNearestVerticalScrollParent } from '@/utils/dom'
import MediaRow from '@/components/media/MediaRow.vue'
import MediaTabs from '@/components/tabs/MediaTabs.vue'
import { MEDIA_TYPE } from '@/constant'
import { DESKTOP_FONT_SIZE_SCALE } from '@/constant/config'

const props = defineProps({
  modelValue: {
    type: [String, Number],
    required: true,
  },

  videoData: { type: Array },
  photoData: { type: Array },
  subsData: { type: Array },
  shopData: { type: Array },
  freeData: { type: Array },

  videoLoading: { type: Boolean, default: false },
  photoLoading: { type: Boolean, default: false },
  subsLoading: { type: Boolean, default: false },
  shopLoading: { type: Boolean, default: false },
  freeLoading: { type: Boolean, default: false },

  videoNoMore: { type: Boolean, default: false },
  photoNoMore: { type: Boolean, default: false },
  subsNoMore: { type: Boolean, default: false },
  shopNoMore: { type: Boolean, default: false },
  freeNoMore: { type: Boolean, default: false },

  previewMode: { type: Boolean, default: false },
  previewVisitor: { type: Boolean, default: false },
  selectorMode: { type: Boolean, default: false },
  selectedItems: { type: Array, default: () => [] },
  scheduled: { type: Boolean, default: false },

  heightTrimPx: { type: Number, default: 0 },
})

const emit = defineEmits(['update:modelValue', 'intersect', 'click:item', 'bounding', 'update:selectedItems'])

const isVideoPhoto = computed(() => !!props.videoData && !!props.photoData && !props.subsData && !props.shopData && !props.freeData) // prettier-ignore
const isSubsShopFree = computed(() => !props.videoData && !props.photoData && !!props.subsData && !!props.shopData && !!props.freeData) // prettier-ignore
const isOnlySubs = computed(() => !props.videoData && !props.photoData && !!props.subsData && !props.shopData && !props.freeData) // prettier-ignore

const TAB_OPTIONS = Object.freeze({
  [MEDIA_TYPE.VIDEO]: { value: MEDIA_TYPE.VIDEO, icon: 'video', activeIcon: 'videoActive' },
  [MEDIA_TYPE.PHOTO]: { value: MEDIA_TYPE.PHOTO, icon: 'photo', activeIcon: 'photoActive' },
  [MEDIA_TYPE.SUBS]: { value: MEDIA_TYPE.SUBS, label: 'info.media.subs' },
  [MEDIA_TYPE.SHOP]: { value: MEDIA_TYPE.SHOP, label: 'info.media.shop' },
  [MEDIA_TYPE.FREE]: { value: MEDIA_TYPE.FREE, label: 'info.media.free' },
})
const currTab = computed({
  get: () => props.modelValue,
  set: (value) => emit('update:modelValue', value),
})
const tabs = computed(() => {
  if (isVideoPhoto.value) return [TAB_OPTIONS[MEDIA_TYPE.VIDEO], TAB_OPTIONS[MEDIA_TYPE.PHOTO]]
  if (isSubsShopFree.value) return [TAB_OPTIONS[MEDIA_TYPE.FREE],TAB_OPTIONS[MEDIA_TYPE.SUBS], TAB_OPTIONS[MEDIA_TYPE.SHOP]] // prettier-ignore
  if (isOnlySubs.value) return [TAB_OPTIONS[MEDIA_TYPE.SUBS]]
  return [] // 是誰沒傳東西還敢建立這個元件？？
})
const atVideo = computed(() => currTab.value === TAB_OPTIONS[MEDIA_TYPE.VIDEO].value)
const atPhoto = computed(() => currTab.value === TAB_OPTIONS[MEDIA_TYPE.PHOTO].value)
const atSubs = computed(() => currTab.value === TAB_OPTIONS[MEDIA_TYPE.SUBS].value)
const atShop = computed(() => currTab.value === TAB_OPTIONS[MEDIA_TYPE.SHOP].value)
const atFree = computed(() => currTab.value === TAB_OPTIONS[MEDIA_TYPE.FREE].value)

const { isDesktop } = storeToRefs(useAppStore())
const { height } = useWindowSize()
const minHeight = computed(() => {
  const scale = isDesktop.value ? DESKTOP_FONT_SIZE_SCALE : 1
  return `${(height.value - props.heightTrimPx) / (16 * scale)}rem`
})

function onIntersect() {
  emit('intersect')
}
function onItemClick(index) {
  emit('click:item', index)
}
function onBounding(bounds, index) {
  emit('bounding', bounds, index)
}

const { open } = usePopupMessageStore()
const selectedItems = ref(props.selectedItems)
watch(
  () => props.selectedItems,
  (v) => {
    selectedItems.value = v
  },
)
provide('selectorMode', props.selectorMode)
provide('selectedItems', selectedItems)
function onSelected(item) {
  const selectedIndex = selectedItems.value.findIndex((selectedItem) => selectedItem.id === item.id)

  if (selectedItems.value.length >= 10 && selectedIndex === -1) {
    open($t('info.pushMsgMost'))
    return
  }

  if (selectedIndex !== -1) {
    selectedItems.value.splice(selectedIndex, 1)
  } else {
    selectedItems.value.push(item)
  }

  emit('update:selectedItems', selectedItems.value)
}

const scheduled = ref(props.scheduled)
watch(
  () => props.scheduled,
  (v) => (scheduled.value = v),
)
provide('scheduled', scheduled)

const root = ref(null)
const scrollParent = ref(null)
const { top: rootTop } = useElementBounding(root)
const { top: scrollParentTop } = useElementBounding(scrollParent)
const rootScrollOffset = computed(() => Math.round(scrollParentTop.value - rootTop.value))
onMounted(() => (scrollParent.value = findNearestVerticalScrollParent(root.value)))

const tabConfigs = {
  video: {
    scrollTop: 0,
    // style: computed(() => (atVideo.value ? 0 : rootScrollTop.value - tabConfigs.video.scrollTop.value)),
  },
  photo: {
    scrollTop: 0,
    // style: computed(() => (atPhoto.value ? 0 : rootScrollTop.value - tabConfigs.photo.scrollTop.value)),
  },
  subs: {
    scrollTop: 0,
    // style: computed(() => (atSubs.value ? 0 : rootScrollTop.value - tabConfigs.subs.scrollTop.value)),
  },
  shop: {
    scrollTop: 0,
    // style: computed(() => (atShop.value ? 0 : rootScrollTop.value - tabConfigs.shop.scrollTop.value)),
  },
  free: {
    scrollTop: 0,
    // style: computed(() => (atFree.value ? 0 : rootScrollTop.value - tabConfigs.free.scrollTop.value)),
  },
}
const currTabConfig = computed(() => {
  if (atVideo.value) {
    return tabConfigs.video
  } else if (atPhoto.value) {
    return tabConfigs.photo
  } else if (atSubs.value) {
    return tabConfigs.subs
  } else if (atShop.value) {
    return tabConfigs.shop
  } else if (atFree.value) {
    return tabConfigs.free
  } else {
    return null
  }
})

watch(rootScrollOffset, (v) => {
  if (v < 0) {
    Object.values(tabConfigs).forEach((o) => (o.scrollTop = 0))
  } else {
    currTabConfig.value.scrollTop = v
  }
})
watch(currTab, () => {
  if (rootScrollOffset.value < 0) return
  const rootOffsetTop = (scrollParent.value?.scrollHeight - root.value?.clientHeight || 0) + 1
  const scrollTop = currTabConfig.value?.scrollTop || 0
  waitThenScrollTo(rootOffsetTop + scrollTop)
})
function waitThenScrollTo(top) {
  cancelAnimationFrame(waitThenScrollTo.animId)
  if (!scrollParent.value) {
    return
  }
  const { scrollHeight, clientHeight } = scrollParent.value
  // 扣掉 2 是因為精准度很難完全抓到
  if (top - 2 <= scrollHeight - clientHeight) {
    scrollParent.value.scrollTo({ top, behavior: 'instant' })
  } else {
    waitThenScrollTo.animId = requestAnimationFrame(() => waitThenScrollTo(top))
  }
}

// watchEffect(() => {
//   console.log(
//     // 'video',
//     // tabConfigs.video.scrollTop.value,
//     // 'photo',
//     // tabConfigs.photo.scrollTop.value,
//     'subs',
//     tabConfigs.subs.scrollTop.value,
//     'shop',
//     tabConfigs.shop.scrollTop.value,
//     'free',
//     tabConfigs.free.scrollTop.value,
//   )
// })
</script>

<style lang="scss" scoped>
.media-wall {
  .tabs {
    position: sticky;
    top: 0;
    z-index: 1;
  }
}
</style>
